package com.feishi.core.media.javacv.util;



import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameConverter.*;
import org.opencv.core.CvType;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;

import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgcodecs.imencode;
import static org.bytedeco.javacpp.opencv_imgproc.*;

/**
 * @version 1.0
 * @auth caixq
 * @time 18-4-20 11:32
 **/
public class OpenCvUtil {
    private static ToIplImage converter = new ToIplImage();

    public static void converter(Frame frame) {

        // 将Frame转为Mat
        Mat mat = converter.convertToMat(frame);

        // 将Mat转为Frame
        Frame convertFrame1 = converter.convert(mat);

        // 将Frame转为IplImage
        IplImage image1 = converter.convertToIplImage(frame);
        IplImage image2 = converter.convert(frame);

        // 将IplImage转为Frame
        Frame convertFrame2 = converter.convert(image1);

        //Mat转IplImage
        IplImage matImage = new IplImage(mat);

        //IplImage转Mat
        Mat mat2 = new Mat(matImage);

    }
    public static Mat cut( Mat img, int width, int height,int startX, int startY){

        Mat imgDesc = new Mat(width, height, CvType.CV_8UC3);

        Mat imgROI = new Mat(img, new Rect(startX, startY, width, height));

        imgROI.copyTo(imgDesc);

        return imgDesc;
    }
    public static BufferedImage MatToBufImg(Mat mat, String fileExtension){
        byte[] byteArray = MatToBytes(mat,fileExtension);
        BufferedImage bufImage = null;
        try {
            InputStream in = new ByteArrayInputStream(byteArray);
            bufImage = ImageIO.read(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufImage;
    }

    public static BufferedImage MatToBufImg(Mat mat){
        if (mat.size().height() > 0 && mat.size().width() > 0) {
            BufferedImage image = new BufferedImage(mat.size().width(), mat.size().height(), BufferedImage.TYPE_3BYTE_BGR);
            DataBufferByte dataBuffer = (DataBufferByte) image.getRaster().getDataBuffer();

            byte[] data = dataBuffer.getData();

            ByteBuffer bf=mat.createBuffer();
            bf.get(data);
            return image;
        }

        return null;
    }
    public static ByteArrayInputStream MatToStream(Mat mat, String fileExtension){

        return new ByteArrayInputStream(MatToBytes(mat,fileExtension));
    }

    public static byte[] MatToBytes(Mat mat, String fileExtension) {
        ByteBuffer bf= ByteBuffer.allocate(mat.createBuffer().remaining());
        imencode(fileExtension,mat,bf);
        return ByteBufferToBytes(bf);
    }
    public static byte[] MatToBytes(Mat mat) {
        ByteBuffer bf=mat.createBuffer();
        return ByteBufferToBytes(bf);
    }
    private static byte[] ByteBufferToBytes(ByteBuffer bf) {
        byte[] result=new byte[bf.remaining()];
        bf.get(result);
        return result;
    }

    public static ByteArrayInputStream MatToStream(Mat mat){
        ByteBuffer bf=mat.createBuffer();

        return new ByteArrayInputStream(ByteBufferToBytes(bf));
    }





    private IplImage rotateImage(IplImage img)
    {
      /*IplImage img_rotate = IplImage.create(img.width(), img.height(),  IPL_DEPTH_8U, 2);
      //旋转中心为图像中心
      CvPoint2D32f center = new CvPoint2D32f();
      center.x(img.width()/2.0f+0.5f);
      center.y(img.height()/2.0f+0.5f);
      //计算二维旋转的仿射变换矩阵
      CvMat cvMat = cvCreateMat(2, 3, CV_32F);

      cvZero (img_rotate);
      cv2DRotationMatrix( center, degree,1.0, cvMat);*/

        //变换图像，并用黑色填充其余值
        //cvWarpAffine(img,img_rotate, cvMat,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll(0) );
        IplImage img_rotate = IplImage.create(img.height(),img.width(),  IPL_DEPTH_8U, 2);
        cvTranspose(img, img_rotate);
        cvTranspose(img_rotate, img);
        //cvTranspose(img, img_rotate);
        cvFlip(img,null,-1);

        return img;
    }

    public static IplImage rotate(IplImage image, double angle) {

        IplImage copy = cvCloneImage(image);
        IplImage rotatedImage = cvCreateImage(cvGetSize(copy), copy.depth(), copy.nChannels());


        //Define Rotational Matrix
        CvMat mapMatrix = cvCreateMat(2, 3, CV_32FC1);


        //Define Mid Point
        CvPoint2D32f centerPoint = new CvPoint2D32f();
        centerPoint.x(copy.width() / 2);
        centerPoint.y(copy.height() / 2);


        //Get Rotational Matrix
        cv2DRotationMatrix(centerPoint, angle, 1.0, mapMatrix);


        //Rotate the Image
        cvWarpAffine(copy, rotatedImage, mapMatrix, CV_INTER_CUBIC + CV_WARP_FILL_OUTLIERS, cvScalarAll(170));
        cvReleaseImage(copy);
        cvReleaseMat(mapMatrix);


        return rotatedImage;
    }
}
